import time
import threading
import sys
import json
import librosa
import soundfile as sf
import os

# 获取当前文件所在目录（libs）的路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 将当前目录添加到Python路径
sys.path.insert(0, current_dir)



import nls

URL = "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1"
TOKEN = '1a9e192b7181407ea056357e64e9c26b'  # 请确保token有效
APPKEY = 'RgY65M8PEqOJqaGs'


class TestSt:
    def __init__(self, tid, test_file):
        self.__th = threading.Thread(target=self.__test_run)
        self.__id = tid
        self.__test_file = test_file
        self.final_result = ""
        self.__completed = False

    def loadfile(self, filename):
        try:
            with open(filename, "rb") as f:
                self.__data = f.read()
            print(f"成功加载文件: {filename}, 文件大小: {len(self.__data)} 字节")
        except Exception as e:
            print(f"加载文件失败: {e}")
            self.__data = b""

    def start(self):
        self.loadfile(self.__test_file)
        self.__th.start()

    def is_completed(self):
        """检查线程是否完成"""
        return not self.__th.is_alive()

    def wait_for_completion(self):
        """等待线程完成"""
        self.__th.join()
        return self.__completed

    def test_on_sentence_begin(self, message, *args):
        print(f"{self.__id} test_on_sentence_begin: {message}")

    def test_on_sentence_end(self, message, *args):
        print(f"{self.__id} test_on_sentence_end: {message}")

        try:
            # 检查message是否是字符串并尝试解析
            if isinstance(message, str):
                message_dict = json.loads(message)
            else:
                message_dict = message

            self.final_result = message_dict.get('payload', {}).get('result', '')

            if self.final_result:
                # 获取原音频文件的目录和文件名（不含扩展名）
                base_name = os.path.basename(self.__test_file)
                file_name_without_ext = os.path.splitext(base_name)[0]
                directory = os.path.dirname(self.__test_file)

                # 创建结果文件路径
                result_file = os.path.join(directory, f"{file_name_without_ext}.txt")

                print(f"保存结果到: {result_file}")

                # 追加模式写入结果
                with open(result_file, 'a', encoding='utf-8') as file:
                    file.write(self.final_result + "\n")

                print(f"{self.__id} 最终识别结果: {self.final_result}")
            else:
                print(f"{self.__id} 未获取到识别结果")

        except json.JSONDecodeError as e:
            print(f"{self.__id} JSON解析失败: {e}")
        except Exception as e:
            print(f"{self.__id} 保存文件时出错: {e}")

    def test_on_start(self, message, *args):
        print(f"{self.__id} test_on_start: {message}")

    def test_on_error(self, message, *args):
        print(f"{self.__id} on_error: {message}")

    def test_on_close(self, *args):
        print(f"{self.__id} on_close: {args}")

    def test_on_result_chg(self, message, *args):
        print(f"{self.__id} test_on_chg: {message}")

    def test_on_completed(self, message, *args):
        print(f"{self.__id} on_completed: args=>{args} message=>{message}")
        self.__completed = True

    def __test_run(self):
        print(f"线程 {self.__id} 开始执行...")

        if not self.__data:
            print(f"{self.__id}: 无音频数据，跳过处理")
            self.__completed = True
            return

        try:
            sr = nls.NlsSpeechTranscriber(
                url=URL,
                token=TOKEN,
                appkey=APPKEY,
                on_sentence_begin=self.test_on_sentence_begin,
                on_sentence_end=self.test_on_sentence_end,
                on_start=self.test_on_start,
                on_result_changed=self.test_on_result_chg,
                on_completed=self.test_on_completed,
                on_error=self.test_on_error,
                on_close=self.test_on_close,
                callback_args=[self.__id]
            )

            print(f"{self.__id}: 会话开始")
            r = sr.start(
                aformat="pcm",
                enable_intermediate_result=True,
                enable_punctuation_prediction=True,
                enable_inverse_text_normalization=True
            )

            # 发送音频数据
            slice_size = 640  # 每次发送640字节
            for i in range(0, len(self.__data), slice_size):
                chunk = self.__data[i:i + slice_size]
                if len(chunk) < slice_size:
                    # 填充最后一个不完整的块
                    chunk += b'\x00' * (slice_size - len(chunk))
                sr.send_audio(chunk)
                time.sleep(0.01)

            # 可选的控制命令
            sr.ctrl(ex={"test": "tttt"})
            time.sleep(1)

            r = sr.stop()
            print(f"{self.__id}: 识别停止: {r}")

        except Exception as e:
            print(f"{self.__id}: 处理过程中出现错误: {e}")
        finally:
            self.__completed = True
            print(f"{self.__id}: 线程执行完成")


def singleruntest(inputWav):
    """单线程运行测试"""
    print(f"开始处理音频文件: {inputWav}")

    if not os.path.exists(inputWav):
        print(f"文件不存在: {inputWav}")
        return

    t = TestSt("single_thread", inputWav)
    t.start()

    # 等待线程完成
    while not t.is_completed():
        time.sleep(0.1)

    print("处理完成！")


def multiruntest(inputWav, num=3):
    """多线程运行测试"""
    print(f"开始多线程处理音频文件: {inputWav}, 线程数: {num}")

    if not os.path.exists(inputWav):
        print(f"文件不存在: {inputWav}")
        return

    threads = []
    for i in range(num):
        name = f"thread_{i}"
        t = TestSt(name, inputWav)
        t.start()
        threads.append(t)

    # 等待所有线程完成
    all_completed = False
    while not all_completed:
        all_completed = True
        for t in threads:
            if not t.is_completed():
                all_completed = False
                break
        time.sleep(0.1)

    print("所有线程处理完成！")


# 或者更简单的版本 - 直接使用线程的join方法
def singleruntest_simple(inputWav):
    """简单的单线程运行测试"""
    print(f"开始处理音频文件: {inputWav}")

    if not os.path.exists(inputWav):
        print(f"文件不存在: {inputWav}")
        return   0

    t = TestSt("single_thread", inputWav)
    t.start()

    # 直接使用线程对象的join方法
    t._TestSt__th.join()
    print("处理完成！")
    return  1

def multiruntest_simple(inputWav, num=3):
    """简单的多线程运行测试"""
    print(f"开始多线程处理音频文件: {inputWav}, 线程数: {num}")

    if not os.path.exists(inputWav):
        print(f"文件不存在: {inputWav}")
        return

    threads = []
    for i in range(num):
        name = f"thread_{i}"
        t = TestSt(name, inputWav)
        t.start()
        threads.append(t)

    # 直接等待所有线程完成
    for t in threads:
        t._TestSt__th.join()

    print("所有线程处理完成！")



# if __name__ == "__main__":
#     nls.enableTrace(False)  # 关闭详细日志
#
#     # 使用示例
#     inputWav = "your_audio_file.wav"  # 请替换为您的音频文件路径
#
#     # 方法1: 使用简单的版本（推荐）
#     singleruntest_simple(inputWav)

    # 或者多线程运行（注意：阿里云API可能有并发限制）
    # multiruntest_simple(inputWav, 2)


